/** 
  Copyright (c) 2008, 2009 Claudio Imbrenda
  This program is released under the terms of the
  GNU GPL version 3 or later.
*/
package macchina.nastri;

import java.io.*;
import macchina.*;

public class NastroFileNastro implements AdattatoreEntrata{

  BufferedReader inf;
  boolean isloop;
  
  public NastroFileNastro(File f)throws FileNotFoundException{
    inf=new BufferedReader(new FileReader(f));
  }
  public NastroFileNastro(String s) throws FileNotFoundException{
    inf=new BufferedReader(new FileReader(s));
  }

  private static byte _val(char c){
      switch(c){
          case 'o':
          case 'O':
          case '*':
          case 'X':
          case 'x':
              return (byte)1;
          case '.':
          case ' ':
          case '_':
              return (byte)0;
      }
      throw new NumberFormatException("not a valid character: "+c);
  }

  public static byte parseNastro(String w){
      byte res=0;
      if(w.length()>6)w=w.trim().toLowerCase();  

      if(w.startsWith("#")||w.startsWith("//")) return -1;
      else if(w.length()==0) return -1;
      else if(w.length()!=5 && w.length()!=6)return AdattatoreEntrata.IOERR;

      try{
        if(w.length()==6){
            if(_val(w.charAt(3))!=0)
                return AdattatoreEntrata.IOERR;
            w=w.substring(0, 3)+w.substring(4,6);
        }
        for(int cx=0;cx<5;cx++){
          res+=_val(w.charAt(cx))<<(4-cx);
        }
//        System.err.println("res="+res);
        return res;
      }catch(IndexOutOfBoundsException e){}
      catch(NumberFormatException e){}
      return AdattatoreEntrata.IOERR;
  }

  private boolean ioerr=false;
  
  public byte read(){
    byte rr=0;
    if(ioerr)
      return AdattatoreEntrata.EOT|AdattatoreEntrata.IOERR;
    
    try{
      do{
        rr = parseNastro(inf.readLine());
      }while(rr==-1);

    }
    catch(IOException ignore){ioerr=true;return read();}
    catch(NumberFormatException ignore){ioerr=true;return read();}
    catch(NullPointerException ignore){
        try{
            if(isloop){
                inf.reset();
                return read();
            }
        }catch(IOException e){ioerr=true;return read();}
        return AdattatoreEntrata.EOT;
    }
    
    if(rr==-1)return AdattatoreEntrata.EOT;

    return rr;
  }

    public void setLoop(boolean v) {
        isloop=v;
    }

    public boolean isLoop() {
        return isloop;
    }

}
